﻿using System;
using System.Collections.Generic;

namespace Tilver.ConsoleTest.Model
{
    /*
     定义了一种一对多的依赖关系,让多个观察对象同时观察某一个主题对象。这个主题在状态发生变化时会通知所有的观察者对象,使它们能够自动更新自己。
     观察者模式组成：
     1.抽象主题(AbstractSubject)类提供抽象类或者一个接口实现。把所有对观察者对象的引用保存在一个聚集里,每个主题可以有任意数量的观察者。抽象主题提供了一个接口,可以增加和删除观察者对象.
     2.抽象观察者(AbstractObserver)类为所有具体观察者定义一个接口,在得到主题时更新自己。这个接口叫做更新接口。抽象观察者用抽象类或者接口实现,更新接口包含一个更新方法(Update)。
     3.具体主题（ConcreteSubject）类，存放具体观察者对象；在具体主题的内部状态改变时，给所有观察者发出通知。具体角色用具体子类实现。
     4.具体观察者（ConcreteObserver）类，实现抽象观察者的更新接口,以便和主题状态协调,具体观察者用具体子类实现。       
     总结：
     观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。
     */
    /// <summary>
    /// 抽象主题
    /// </summary>
    public abstract class AbstractSubject
    {
        public abstract void Attach(AbstractObserver abstractObserver);
        public abstract void Detach(AbstractObserver abstractObserver);
        public abstract void Notify();
    }

    /// <summary>
    /// 具体主题
    /// </summary>
    public class ConcreteAbstractSubject : AbstractSubject
    {
        /// <summary>
        /// 定义多个观察者
        /// </summary>
        private IList<AbstractObserver> _observers = new List<AbstractObserver>();
        private string _subjectState;
        /// <summary>
        /// 具体被观察者状态
        /// </summary>
        public string SubjectState
        {
            get { return _subjectState; }
            set { _subjectState = value; }
        }
        /// <summary>
        /// 增加观察者
        /// </summary>
        /// <param name="abstractObserver"></param>
        public override void Attach(AbstractObserver abstractObserver)
        {
            _observers.Add(abstractObserver);
        }
        /// <summary>
        /// 移除观察者
        /// </summary>
        /// <param name="abstractObserver"></param>
        public override void Detach(AbstractObserver abstractObserver)
        {
            _observers.Remove(abstractObserver);
        }
        /// <summary>
        /// 通知观察者
        /// </summary>
        public override void Notify()
        {
            foreach (AbstractObserver o in _observers)
            {
                o.Update();
            }
        }
    }

    /// <summary>
    /// 抽象观察者
    /// </summary>
    public abstract class AbstractObserver
    {
        public abstract void Update();
    }

    /// <summary>
    /// 具体主题
    /// </summary>
    public class ConcreteAbstractObserver : AbstractObserver
    {
        private string _name;
        private string _observerState;
        private ConcreteAbstractSubject _abstractSubject;
        /// <summary>
        /// 主题
        /// </summary>
        public ConcreteAbstractSubject AbstractSubject
        {
            get { return _abstractSubject; }
            set { _abstractSubject = value; }
        }

        public ConcreteAbstractObserver(ConcreteAbstractSubject _abstractSubject, string name)
        {
            this._abstractSubject = _abstractSubject;
            this._name = name;
        }
        /// <summary>
        /// 更新主题状态
        /// </summary>
        public override void Update()
        {
            _observerState = _abstractSubject.SubjectState;
            Console.WriteLine("观察者{0}的新状态是{1}", _name, _observerState);
        }

    }

}
